﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;

namespace LostLib.Algorithms
{
	public static class DiffUtils
	{
		public static IEnumerable<Diff<char>> Diff(this string original, string @new)
		{
			var orig = original.ToCharArray();
			var n = @new.ToCharArray();
			return Diff<char>.GetDiff(orig, n);
		}

		public static string ApplyPatch(this string original, IEnumerable<Diff<char>> patch)
		{
			var orig = original.ToCharArray();

			var result = patch.Apply(orig);
			return new string(result.ToArray());
		}

		public static void Diff(string originalPath, string newPath, string diffOutput)
		{
			var original = File.ReadAllBytes(originalPath);
			var @new = File.ReadAllBytes(newPath);

			var diff = Diff<byte>.GetDiff(original, @new).ToArray();

			using (var dest = new FileStream(diffOutput, FileMode.Create, FileAccess.Write, FileShare.ReadWrite))
			using (var gzip = new GZipStream(dest, CompressionMode.Compress))
			{
				var formatter = new BinaryFormatter();

				formatter.Serialize(gzip, diff);

				gzip.Close();
				dest.Close();
			}
		}

		public static void ApplyPatch(string targetPath, string newPath, string patchPath)
		{
			var original = File.ReadAllBytes(targetPath);

			Diff<byte>[] diff;

			using(var patchStream = new FileStream(patchPath, FileMode.Open, FileAccess.Read, FileShare.Read))
			using (var gzip = new GZipStream(patchStream, CompressionMode.Decompress))
			{
				var formatter = new BinaryFormatter();

				diff = (Diff<byte>[])formatter.Deserialize(gzip);
			}

			var @new = diff.Apply(original);

			File.WriteAllBytes(newPath, @new.ToArray());
		}
	}
}
